/*
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package javax.swing;

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.security.AccessController;
import javax.accessibility.*;
import javax.swing.plaf.RootPaneUI;
import java.util.Vector;
import java.io.Serializable;
import javax.swing.border.*;
import sun.awt.AWTAccessor;
import sun.security.action.GetBooleanAction;


/**
 * A lightweight container used behind the scenes by <code>JFrame</code>, <code>JDialog</code>,
 * <code>JWindow</code>, <code>JApplet</code>, and <code>JInternalFrame</code>. For task-oriented
 * information on functionality provided by root panes see <a href="https://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html">How
 * to Use Root Panes</a>, a section in <em>The Java Tutorial</em>.
 *
 * <p> The following image shows the relationships between the classes that use root panes. <p
 * style="text-align:center"><img src="doc-files/JRootPane-1.gif" alt="The following text describes
 * this graphic." HEIGHT=484 WIDTH=629></p> The &quot;heavyweight&quot; components (those that
 * delegate to a peer, or native component on the host system) are shown with a darker, heavier box.
 * The four heavyweight JFC/Swing containers (<code>JFrame</code>, <code>JDialog</code>,
 * <code>JWindow</code>, and <code>JApplet</code>) are shown in relation to the AWT classes they
 * extend. These four components are the only heavyweight containers in the Swing library. The
 * lightweight container <code>JInternalFrame</code> is also shown. All five of these JFC/Swing
 * containers implement the <code>RootPaneContainer</code> interface, and they all delegate their
 * operations to a <code>JRootPane</code> (shown with a little "handle" on top). <blockquote>
 * <b>Note:</b> The <code>JComponent</code> method <code>getRootPane</code> can be used to obtain
 * the <code>JRootPane</code> that contains a given component. </blockquote> <table
 * style="float:right" border="0" summary="layout"> <tr> <td align="center"> <img
 * src="doc-files/JRootPane-2.gif" alt="The following text describes this graphic." HEIGHT=386
 * WIDTH=349> </td> </tr> </table> The diagram at right shows the structure of a
 * <code>JRootPane</code>. A <code>JRootpane</code> is made up of a <code>glassPane</code>, an
 * optional <code>menuBar</code>, and a <code>contentPane</code>. (The <code>JLayeredPane</code>
 * manages the <code>menuBar</code> and the <code>contentPane</code>.) The <code>glassPane</code>
 * sits over the top of everything, where it is in a position to intercept mouse movements. Since
 * the <code>glassPane</code> (like the <code>contentPane</code>) can be an arbitrary component, it
 * is also possible to set up the <code>glassPane</code> for drawing. Lines and images on the
 * <code>glassPane</code> can then range over the frames underneath without being limited by their
 * boundaries. <p> Although the <code>menuBar</code> component is optional, the
 * <code>layeredPane</code>, <code>contentPane</code>, and <code>glassPane</code> always exist.
 * Attempting to set them to <code>null</code> generates an exception. <p> To add components to the
 * <code>JRootPane</code> (other than the optional menu bar), you add the object to the
 * <code>contentPane</code> of the <code>JRootPane</code>, like this:
 * <pre>
 *       rootPane.getContentPane().add(child);
 * </pre>
 * The same principle holds true for setting layout managers, removing components, listing children,
 * etc. All these methods are invoked on the <code>contentPane</code> instead of on the
 * <code>JRootPane</code>. <blockquote> <b>Note:</b> The default layout manager for the
 * <code>contentPane</code> is a <code>BorderLayout</code> manager. However, the
 * <code>JRootPane</code> uses a custom <code>LayoutManager</code>. So, when you want to change the
 * layout manager for the components you added to a <code>JRootPane</code>, be sure to use code like
 * this:
 * <pre>
 *    rootPane.getContentPane().setLayout(new BoxLayout());
 * </pre></blockquote>
 * If a <code>JMenuBar</code> component is set on the <code>JRootPane</code>, it is positioned along
 * the upper edge of the frame. The <code>contentPane</code> is adjusted in location and size to
 * fill the remaining area. (The <code>JMenuBar</code> and the <code>contentPane</code> are added to
 * the <code>layeredPane</code> component at the <code>JLayeredPane.FRAME_CONTENT_LAYER</code>
 * layer.) <p> The <code>layeredPane</code> is the parent of all children in the
 * <code>JRootPane</code> -- both as the direct parent of the menu and the grandparent of all
 * components added to the <code>contentPane</code>. It is an instance of <code>JLayeredPane</code>,
 * which provides the ability to add components at several layers. This capability is very useful
 * when working with menu popups, dialog boxes, and dragging -- situations in which you need to
 * place a component on top of all other components in the pane. <p> The <code>glassPane</code> sits
 * on top of all other components in the <code>JRootPane</code>. That provides a convenient place to
 * draw above all other components, and makes it possible to intercept mouse events, which is useful
 * both for dragging and for drawing. Developers can use <code>setVisible</code> on the
 * <code>glassPane</code> to control when the <code>glassPane</code> displays over the other
 * children. By default the <code>glassPane</code> is not visible. <p> The custom
 * <code>LayoutManager</code> used by <code>JRootPane</code> ensures that: <OL> <LI>The
 * <code>glassPane</code> fills the entire viewable area of the <code>JRootPane</code> (bounds -
 * insets). <LI>The <code>layeredPane</code> fills the entire viewable area of the
 * <code>JRootPane</code>. (bounds - insets) <LI>The <code>menuBar</code> is positioned at the upper
 * edge of the <code>layeredPane</code>. <LI>The <code>contentPane</code> fills the entire viewable
 * area, minus the <code>menuBar</code>, if present. </OL> Any other views in the
 * <code>JRootPane</code> view hierarchy are ignored. <p> If you replace the
 * <code>LayoutManager</code> of the <code>JRootPane</code>, you are responsible for managing all of
 * these views. So ordinarily you will want to be sure that you change the layout manager for the
 * <code>contentPane</code> rather than for the <code>JRootPane</code> itself! <p> The painting
 * architecture of Swing requires an opaque <code>JComponent</code> to exist in the containment
 * hierarchy above all other components. This is typically provided by way of the content pane. If
 * you replace the content pane, it is recommended that you make the content pane opaque by way of
 * <code>setOpaque(true)</code>. Additionally, if the content pane overrides
 * <code>paintComponent</code>, it will need to completely fill in the background in an opaque color
 * in <code>paintComponent</code>. <p> <strong>Warning:</strong> Swing is not thread safe. For more
 * information see <a href="package-summary.html#threading">Swing's Threading Policy</a>. <p>
 * <strong>Warning:</strong> Serialized objects of this class will not be compatible with future
 * Swing releases. The current serialization support is appropriate for short term storage or RMI
 * between applications running the same version of Swing.  As of 1.4, support for long term storage
 * of all JavaBeans&trade; has been added to the <code>java.beans</code> package. Please see {@link
 * java.beans.XMLEncoder}.
 *
 * @author David Kloba
 * @see JLayeredPane
 * @see JMenuBar
 * @see JWindow
 * @see JFrame
 * @see JDialog
 * @see JApplet
 * @see JInternalFrame
 * @see JComponent
 * @see BoxLayout
 * @see <a href="http://java.sun.com/products/jfc/tsc/articles/mixing/"> Mixing Heavy and Light
 * Components</a>
 */
/// PENDING(klobad) Who should be opaque in this component?
@SuppressWarnings("serial")
public class JRootPane extends JComponent implements Accessible {

  private static final String uiClassID = "RootPaneUI";

  /**
   * Whether or not we should dump the stack when true double buffering
   * is disabled. Default is false.
   */
  private static final boolean LOG_DISABLE_TRUE_DOUBLE_BUFFERING;

  /**
   * Whether or not we should ignore requests to disable true double
   * buffering. Default is false.
   */
  private static final boolean IGNORE_DISABLE_TRUE_DOUBLE_BUFFERING;

  /**
   * Constant used for the windowDecorationStyle property. Indicates that
   * the <code>JRootPane</code> should not provide any sort of
   * Window decorations.
   *
   * @since 1.4
   */
  public static final int NONE = 0;

  /**
   * Constant used for the windowDecorationStyle property. Indicates that
   * the <code>JRootPane</code> should provide decorations appropriate for
   * a Frame.
   *
   * @since 1.4
   */
  public static final int FRAME = 1;

  /**
   * Constant used for the windowDecorationStyle property. Indicates that
   * the <code>JRootPane</code> should provide decorations appropriate for
   * a Dialog.
   *
   * @since 1.4
   */
  public static final int PLAIN_DIALOG = 2;

  /**
   * Constant used for the windowDecorationStyle property. Indicates that
   * the <code>JRootPane</code> should provide decorations appropriate for
   * a Dialog used to display an informational message.
   *
   * @since 1.4
   */
  public static final int INFORMATION_DIALOG = 3;

  /**
   * Constant used for the windowDecorationStyle property. Indicates that
   * the <code>JRootPane</code> should provide decorations appropriate for
   * a Dialog used to display an error message.
   *
   * @since 1.4
   */
  public static final int ERROR_DIALOG = 4;

  /**
   * Constant used for the windowDecorationStyle property. Indicates that
   * the <code>JRootPane</code> should provide decorations appropriate for
   * a Dialog used to display a <code>JColorChooser</code>.
   *
   * @since 1.4
   */
  public static final int COLOR_CHOOSER_DIALOG = 5;

  /**
   * Constant used for the windowDecorationStyle property. Indicates that
   * the <code>JRootPane</code> should provide decorations appropriate for
   * a Dialog used to display a <code>JFileChooser</code>.
   *
   * @since 1.4
   */
  public static final int FILE_CHOOSER_DIALOG = 6;

  /**
   * Constant used for the windowDecorationStyle property. Indicates that
   * the <code>JRootPane</code> should provide decorations appropriate for
   * a Dialog used to present a question to the user.
   *
   * @since 1.4
   */
  public static final int QUESTION_DIALOG = 7;

  /**
   * Constant used for the windowDecorationStyle property. Indicates that
   * the <code>JRootPane</code> should provide decorations appropriate for
   * a Dialog used to display a warning message.
   *
   * @since 1.4
   */
  public static final int WARNING_DIALOG = 8;

  private int windowDecorationStyle;

  /**
   * The menu bar.
   */
  protected JMenuBar menuBar;

  /**
   * The content pane.
   */
  protected Container contentPane;

  /**
   * The layered pane that manages the menu bar and content pane.
   */
  protected JLayeredPane layeredPane;

  /**
   * The glass pane that overlays the menu bar and content pane,
   * so it can intercept mouse movements and such.
   */
  protected Component glassPane;
  /**
   * The button that gets activated when the pane has the focus and
   * a UI-specific action like pressing the <b>Enter</b> key occurs.
   */
  protected JButton defaultButton;
  /**
   * As of Java 2 platform v1.3 this unusable field is no longer used.
   * To override the default button you should replace the <code>Action</code>
   * in the <code>JRootPane</code>'s <code>ActionMap</code>. Please refer to
   * the key bindings specification for further details.
   *
   * @see #defaultButton
   * @deprecated As of Java 2 platform v1.3.
   */
  @Deprecated
  protected DefaultAction defaultPressAction;
  /**
   * As of Java 2 platform v1.3 this unusable field is no longer used.
   * To override the default button you should replace the <code>Action</code>
   * in the <code>JRootPane</code>'s <code>ActionMap</code>. Please refer to
   * the key bindings specification for further details.
   *
   * @see #defaultButton
   * @deprecated As of Java 2 platform v1.3.
   */
  @Deprecated
  protected DefaultAction defaultReleaseAction;

  /**
   * Whether or not true double buffering should be used.  This is typically
   * true, but may be set to false in special situations.  For example,
   * heavy weight popups (backed by a window) set this to false.
   */
  boolean useTrueDoubleBuffering = true;

  static {
    LOG_DISABLE_TRUE_DOUBLE_BUFFERING =
        AccessController.doPrivileged(new GetBooleanAction(
            "swing.logDoubleBufferingDisable"));
    IGNORE_DISABLE_TRUE_DOUBLE_BUFFERING =
        AccessController.doPrivileged(new GetBooleanAction(
            "swing.ignoreDoubleBufferingDisable"));
  }

  /**
   * Creates a <code>JRootPane</code>, setting up its
   * <code>glassPane</code>, <code>layeredPane</code>,
   * and <code>contentPane</code>.
   */
  public JRootPane() {
    setGlassPane(createGlassPane());
    setLayeredPane(createLayeredPane());
    setContentPane(createContentPane());
    setLayout(createRootLayout());
    setDoubleBuffered(true);
    updateUI();
  }

  /**
   * {@inheritDoc}
   *
   * @since 1.6
   */
  public void setDoubleBuffered(boolean aFlag) {
    if (isDoubleBuffered() != aFlag) {
      super.setDoubleBuffered(aFlag);
      RepaintManager.currentManager(this).doubleBufferingChanged(this);
    }
  }

  /**
   * Returns a constant identifying the type of Window decorations the
   * <code>JRootPane</code> is providing.
   *
   * @return One of <code>NONE</code>, <code>FRAME</code>, <code>PLAIN_DIALOG</code>,
   * <code>INFORMATION_DIALOG</code>, <code>ERROR_DIALOG</code>, <code>COLOR_CHOOSER_DIALOG</code>,
   * <code>FILE_CHOOSER_DIALOG</code>, <code>QUESTION_DIALOG</code> or <code>WARNING_DIALOG</code>.
   * @see #setWindowDecorationStyle
   * @since 1.4
   */
  public int getWindowDecorationStyle() {
    return windowDecorationStyle;
  }

  /**
   * Sets the type of Window decorations (such as borders, widgets for
   * closing a Window, title ...) the <code>JRootPane</code> should
   * provide. The default is to provide no Window decorations
   * (<code>NONE</code>).
   * <p>
   * This is only a hint, and some look and feels may not support
   * this.
   * This is a bound property.
   *
   * @param windowDecorationStyle Constant identifying Window decorations to provide.
   * @throws IllegalArgumentException if <code>style</code> is not one of: <code>NONE</code>,
   * <code>FRAME</code>, <code>PLAIN_DIALOG</code>, <code>INFORMATION_DIALOG</code>,
   * <code>ERROR_DIALOG</code>, <code>COLOR_CHOOSER_DIALOG</code>, <code>FILE_CHOOSER_DIALOG</code>,
   * <code>QUESTION_DIALOG</code>, or <code>WARNING_DIALOG</code>.
   * @beaninfo bound: true enum: NONE                   JRootPane.NONE FRAME
   * JRootPane.FRAME PLAIN_DIALOG           JRootPane.PLAIN_DIALOG INFORMATION_DIALOG
   * JRootPane.INFORMATION_DIALOG ERROR_DIALOG           JRootPane.ERROR_DIALOG COLOR_CHOOSER_DIALOG
   *   JRootPane.COLOR_CHOOSER_DIALOG FILE_CHOOSER_DIALOG    JRootPane.FILE_CHOOSER_DIALOG
   * QUESTION_DIALOG        JRootPane.QUESTION_DIALOG WARNING_DIALOG
   * JRootPane.WARNING_DIALOG expert: true attribute: visualUpdate true description: Identifies the
   * type of Window decorations to provide
   * @see JDialog#setDefaultLookAndFeelDecorated
   * @see JFrame#setDefaultLookAndFeelDecorated
   * @see LookAndFeel#getSupportsWindowDecorations
   * @since 1.4
   */
  public void setWindowDecorationStyle(int windowDecorationStyle) {
    if (windowDecorationStyle < 0 ||
        windowDecorationStyle > WARNING_DIALOG) {
      throw new IllegalArgumentException("Invalid decoration style");
    }
    int oldWindowDecorationStyle = getWindowDecorationStyle();
    this.windowDecorationStyle = windowDecorationStyle;
    firePropertyChange("windowDecorationStyle",
        oldWindowDecorationStyle,
        windowDecorationStyle);
  }

  /**
   * Returns the L&amp;F object that renders this component.
   *
   * @return <code>LabelUI</code> object
   * @since 1.3
   */
  public RootPaneUI getUI() {
    return (RootPaneUI) ui;
  }

  /**
   * Sets the L&amp;F object that renders this component.
   *
   * @param ui the <code>LabelUI</code> L&amp;F object
   * @beaninfo bound: true hidden: true expert: true attribute: visualUpdate true description: The
   * UI object that implements the Component's LookAndFeel.
   * @see UIDefaults#getUI
   * @since 1.3
   */
  public void setUI(RootPaneUI ui) {
    super.setUI(ui);
  }


  /**
   * Resets the UI property to a value from the current look and feel.
   *
   * @see JComponent#updateUI
   */
  public void updateUI() {
    setUI((RootPaneUI) UIManager.getUI(this));
  }


  /**
   * Returns a string that specifies the name of the L&amp;F class
   * that renders this component.
   *
   * @return the string "RootPaneUI"
   * @see JComponent#getUIClassID
   * @see UIDefaults#getUI
   */
  public String getUIClassID() {
    return uiClassID;
  }

  /**
   * Called by the constructor methods to create the default
   * <code>layeredPane</code>.
   * Bt default it creates a new <code>JLayeredPane</code>.
   *
   * @return the default <code>layeredPane</code>
   */
  protected JLayeredPane createLayeredPane() {
    JLayeredPane p = new JLayeredPane();
    p.setName(this.getName() + ".layeredPane");
    return p;
  }

  /**
   * Called by the constructor methods to create the default
   * <code>contentPane</code>.
   * By default this method creates a new <code>JComponent</code> add sets a
   * <code>BorderLayout</code> as its <code>LayoutManager</code>.
   *
   * @return the default <code>contentPane</code>
   */
  protected Container createContentPane() {
    JComponent c = new JPanel();
    c.setName(this.getName() + ".contentPane");
    c.setLayout(new BorderLayout() {
      /* This BorderLayout subclass maps a null constraint to CENTER.
       * Although the reference BorderLayout also does this, some VMs
       * throw an IllegalArgumentException.
       */
      public void addLayoutComponent(Component comp, Object constraints) {
        if (constraints == null) {
          constraints = BorderLayout.CENTER;
        }
        super.addLayoutComponent(comp, constraints);
      }
    });
    return c;
  }

  /**
   * Called by the constructor methods to create the default
   * <code>glassPane</code>.
   * By default this method creates a new <code>JComponent</code>
   * with visibility set to false.
   *
   * @return the default <code>glassPane</code>
   */
  protected Component createGlassPane() {
    JComponent c = new JPanel();
    c.setName(this.getName() + ".glassPane");
    c.setVisible(false);
    ((JPanel) c).setOpaque(false);
    return c;
  }

  /**
   * Called by the constructor methods to create the default
   * <code>layoutManager</code>.
   *
   * @return the default <code>layoutManager</code>.
   */
  protected LayoutManager createRootLayout() {
    return new RootLayout();
  }

  /**
   * Adds or changes the menu bar used in the layered pane.
   *
   * @param menu the <code>JMenuBar</code> to add
   */
  public void setJMenuBar(JMenuBar menu) {
    if (menuBar != null && menuBar.getParent() == layeredPane) {
      layeredPane.remove(menuBar);
    }
    menuBar = menu;

    if (menuBar != null) {
      layeredPane.add(menuBar, JLayeredPane.FRAME_CONTENT_LAYER);
    }
  }

  /**
   * Specifies the menu bar value.
   *
   * @param menu the <code>JMenuBar</code> to add.
   * @deprecated As of Swing version 1.0.3 replaced by <code>setJMenuBar(JMenuBar menu)</code>.
   */
  @Deprecated
  public void setMenuBar(JMenuBar menu) {
    if (menuBar != null && menuBar.getParent() == layeredPane) {
      layeredPane.remove(menuBar);
    }
    menuBar = menu;

    if (menuBar != null) {
      layeredPane.add(menuBar, JLayeredPane.FRAME_CONTENT_LAYER);
    }
  }

  /**
   * Returns the menu bar from the layered pane.
   *
   * @return the <code>JMenuBar</code> used in the pane
   */
  public JMenuBar getJMenuBar() {
    return menuBar;
  }

  /**
   * Returns the menu bar value.
   *
   * @return the <code>JMenuBar</code> used in the pane
   * @deprecated As of Swing version 1.0.3 replaced by <code>getJMenuBar()</code>.
   */
  @Deprecated
  public JMenuBar getMenuBar() {
    return menuBar;
  }

  /**
   * Sets the content pane -- the container that holds the components
   * parented by the root pane.
   * <p>
   * Swing's painting architecture requires an opaque <code>JComponent</code>
   * in the containment hierarchy. This is typically provided by the
   * content pane. If you replace the content pane it is recommended you
   * replace it with an opaque <code>JComponent</code>.
   *
   * @param content the <code>Container</code> to use for component-contents
   * @throws java.awt.IllegalComponentStateException (a runtime exception) if the content pane
   * parameter is <code>null</code>
   */
  public void setContentPane(Container content) {
    if (content == null) {
      throw new IllegalComponentStateException("contentPane cannot be set to null.");
    }
    if (contentPane != null && contentPane.getParent() == layeredPane) {
      layeredPane.remove(contentPane);
    }
    contentPane = content;

    layeredPane.add(contentPane, JLayeredPane.FRAME_CONTENT_LAYER);
  }

  /**
   * Returns the content pane -- the container that holds the components
   * parented by the root pane.
   *
   * @return the <code>Container</code> that holds the component-contents
   */
  public Container getContentPane() {
    return contentPane;
  }

// PENDING(klobad) Should this reparent the contentPane and MenuBar?

  /**
   * Sets the layered pane for the root pane. The layered pane
   * typically holds a content pane and an optional <code>JMenuBar</code>.
   *
   * @param layered the <code>JLayeredPane</code> to use
   * @throws java.awt.IllegalComponentStateException (a runtime exception) if the layered pane
   * parameter is <code>null</code>
   */
  public void setLayeredPane(JLayeredPane layered) {
    if (layered == null) {
      throw new IllegalComponentStateException("layeredPane cannot be set to null.");
    }
    if (layeredPane != null && layeredPane.getParent() == this) {
      this.remove(layeredPane);
    }
    layeredPane = layered;

    this.add(layeredPane, -1);
  }

  /**
   * Gets the layered pane used by the root pane. The layered pane
   * typically holds a content pane and an optional <code>JMenuBar</code>.
   *
   * @return the <code>JLayeredPane</code> currently in use
   */
  public JLayeredPane getLayeredPane() {
    return layeredPane;
  }

  /**
   * Sets a specified <code>Component</code> to be the glass pane for this
   * root pane.  The glass pane should normally be a lightweight,
   * transparent component, because it will be made visible when
   * ever the root pane needs to grab input events.
   * <p>
   * The new glass pane's visibility is changed to match that of
   * the current glass pane.  An implication of this is that care
   * must be taken when you want to replace the glass pane and
   * make it visible.  Either of the following will work:
   * <pre>
   *   root.setGlassPane(newGlassPane);
   *   newGlassPane.setVisible(true);
   * </pre>
   * or:
   * <pre>
   *   root.getGlassPane().setVisible(true);
   *   root.setGlassPane(newGlassPane);
   * </pre>
   *
   * @param glass the <code>Component</code> to use as the glass pane for this
   * <code>JRootPane</code>
   * @throws NullPointerException if the <code>glass</code> parameter is <code>null</code>
   */
  public void setGlassPane(Component glass) {
    if (glass == null) {
      throw new NullPointerException("glassPane cannot be set to null.");
    }

    AWTAccessor.getComponentAccessor().setMixingCutoutShape(glass,
        new Rectangle());

    boolean visible = false;
    if (glassPane != null && glassPane.getParent() == this) {
      this.remove(glassPane);
      visible = glassPane.isVisible();
    }

    glass.setVisible(visible);
    glassPane = glass;
    this.add(glassPane, 0);
    if (visible) {
      repaint();
    }
  }

  /**
   * Returns the current glass pane for this <code>JRootPane</code>.
   *
   * @return the current glass pane
   * @see #setGlassPane
   */
  public Component getGlassPane() {
    return glassPane;
  }

  /**
   * If a descendant of this <code>JRootPane</code> calls
   * <code>revalidate</code>, validate from here on down.
   * <p>
   * Deferred requests to layout a component and its descendents again.
   * For example, calls to <code>revalidate</code>, are pushed upwards to
   * either a <code>JRootPane</code> or a <code>JScrollPane</code>
   * because both classes override <code>isValidateRoot</code> to return true.
   *
   * @return true
   * @see JComponent#isValidateRoot
   * @see java.awt.Container#isValidateRoot
   */
  @Override
  public boolean isValidateRoot() {
    return true;
  }

  /**
   * The <code>glassPane</code> and <code>contentPane</code>
   * have the same bounds, which means <code>JRootPane</code>
   * does not tiles its children and this should return false.
   * On the other hand, the <code>glassPane</code>
   * is normally not visible, and so this can return true if the
   * <code>glassPane</code> isn't visible. Therefore, the
   * return value here depends upon the visibility of the
   * <code>glassPane</code>.
   *
   * @return true if this component's children don't overlap
   */
  public boolean isOptimizedDrawingEnabled() {
    return !glassPane.isVisible();
  }

  /**
   * {@inheritDoc}
   */
  public void addNotify() {
    super.addNotify();
    enableEvents(AWTEvent.KEY_EVENT_MASK);
  }

  /**
   * {@inheritDoc}
   */
  public void removeNotify() {
    super.removeNotify();
  }


  /**
   * Sets the <code>defaultButton</code> property,
   * which determines the current default button for this <code>JRootPane</code>.
   * The default button is the button which will be activated
   * when a UI-defined activation event (typically the <b>Enter</b> key)
   * occurs in the root pane regardless of whether or not the button
   * has keyboard focus (unless there is another component within
   * the root pane which consumes the activation event,
   * such as a <code>JTextPane</code>).
   * For default activation to work, the button must be an enabled
   * descendent of the root pane when activation occurs.
   * To remove a default button from this root pane, set this
   * property to <code>null</code>.
   *
   * @param defaultButton the <code>JButton</code> which is to be the default button
   * @beaninfo description: The button activated by default in this root pane
   * @see JButton#isDefaultButton
   */
  public void setDefaultButton(JButton defaultButton) {
    JButton oldDefault = this.defaultButton;

    if (oldDefault != defaultButton) {
      this.defaultButton = defaultButton;

      if (oldDefault != null) {
        oldDefault.repaint();
      }
      if (defaultButton != null) {
        defaultButton.repaint();
      }
    }

    firePropertyChange("defaultButton", oldDefault, defaultButton);
  }

  /**
   * Returns the value of the <code>defaultButton</code> property.
   *
   * @return the <code>JButton</code> which is currently the default button
   * @see #setDefaultButton
   */
  public JButton getDefaultButton() {
    return defaultButton;
  }

  final void setUseTrueDoubleBuffering(boolean useTrueDoubleBuffering) {
    this.useTrueDoubleBuffering = useTrueDoubleBuffering;
  }

  final boolean getUseTrueDoubleBuffering() {
    return useTrueDoubleBuffering;
  }

  final void disableTrueDoubleBuffering() {
    if (useTrueDoubleBuffering) {
      if (!IGNORE_DISABLE_TRUE_DOUBLE_BUFFERING) {
        if (LOG_DISABLE_TRUE_DOUBLE_BUFFERING) {
          System.out.println("Disabling true double buffering for " +
              this);
          Thread.dumpStack();
        }
        useTrueDoubleBuffering = false;
        RepaintManager.currentManager(this).
            doubleBufferingChanged(this);
      }
    }
  }

  @SuppressWarnings("serial")
  static class DefaultAction extends AbstractAction {

    JButton owner;
    JRootPane root;
    boolean press;

    DefaultAction(JRootPane root, boolean press) {
      this.root = root;
      this.press = press;
    }

    public void setOwner(JButton owner) {
      this.owner = owner;
    }

    public void actionPerformed(ActionEvent e) {
      if (owner != null && SwingUtilities.getRootPane(owner) == root) {
        ButtonModel model = owner.getModel();
        if (press) {
          model.setArmed(true);
          model.setPressed(true);
        } else {
          model.setPressed(false);
        }
      }
    }

    public boolean isEnabled() {
      return owner.getModel().isEnabled();
    }
  }


  /**
   * Overridden to enforce the position of the glass component as
   * the zero child.
   *
   * @param comp the component to be enhanced
   * @param constraints the constraints to be respected
   * @param index the index
   */
  protected void addImpl(Component comp, Object constraints, int index) {
    super.addImpl(comp, constraints, index);

    /// We are making sure the glassPane is on top.
    if (glassPane != null
        && glassPane.getParent() == this
        && getComponent(0) != glassPane) {
      add(glassPane, 0);
    }
  }

///////////////////////////////////////////////////////////////////////////////
//// Begin Inner Classes
///////////////////////////////////////////////////////////////////////////////


  /**
   * A custom layout manager that is responsible for the layout of
   * layeredPane, glassPane, and menuBar.
   * <p>
   * <strong>Warning:</strong>
   * Serialized objects of this class will not be compatible with
   * future Swing releases. The current serialization support is
   * appropriate for short term storage or RMI between applications running
   * the same version of Swing.  As of 1.4, support for long term storage
   * of all JavaBeans&trade;
   * has been added to the <code>java.beans</code> package.
   * Please see {@link java.beans.XMLEncoder}.
   */
  @SuppressWarnings("serial")
  protected class RootLayout implements LayoutManager2, Serializable {

    /**
     * Returns the amount of space the layout would like to have.
     *
     * @param parent the Container for which this layout manager is being used
     * @return a Dimension object containing the layout's preferred size
     */
    public Dimension preferredLayoutSize(Container parent) {
      Dimension rd, mbd;
      Insets i = getInsets();

      if (contentPane != null) {
        rd = contentPane.getPreferredSize();
      } else {
        rd = parent.getSize();
      }
      if (menuBar != null && menuBar.isVisible()) {
        mbd = menuBar.getPreferredSize();
      } else {
        mbd = new Dimension(0, 0);
      }
      return new Dimension(Math.max(rd.width, mbd.width) + i.left + i.right,
          rd.height + mbd.height + i.top + i.bottom);
    }

    /**
     * Returns the minimum amount of space the layout needs.
     *
     * @param parent the Container for which this layout manager is being used
     * @return a Dimension object containing the layout's minimum size
     */
    public Dimension minimumLayoutSize(Container parent) {
      Dimension rd, mbd;
      Insets i = getInsets();
      if (contentPane != null) {
        rd = contentPane.getMinimumSize();
      } else {
        rd = parent.getSize();
      }
      if (menuBar != null && menuBar.isVisible()) {
        mbd = menuBar.getMinimumSize();
      } else {
        mbd = new Dimension(0, 0);
      }
      return new Dimension(Math.max(rd.width, mbd.width) + i.left + i.right,
          rd.height + mbd.height + i.top + i.bottom);
    }

    /**
     * Returns the maximum amount of space the layout can use.
     *
     * @param target the Container for which this layout manager is being used
     * @return a Dimension object containing the layout's maximum size
     */
    public Dimension maximumLayoutSize(Container target) {
      Dimension rd, mbd;
      Insets i = getInsets();
      if (menuBar != null && menuBar.isVisible()) {
        mbd = menuBar.getMaximumSize();
      } else {
        mbd = new Dimension(0, 0);
      }
      if (contentPane != null) {
        rd = contentPane.getMaximumSize();
      } else {
        // This is silly, but should stop an overflow error
        rd = new Dimension(Integer.MAX_VALUE,
            Integer.MAX_VALUE - i.top - i.bottom - mbd.height - 1);
      }
      return new Dimension(Math.min(rd.width, mbd.width) + i.left + i.right,
          rd.height + mbd.height + i.top + i.bottom);
    }

    /**
     * Instructs the layout manager to perform the layout for the specified
     * container.
     *
     * @param parent the Container for which this layout manager is being used
     */
    public void layoutContainer(Container parent) {
      Rectangle b = parent.getBounds();
      Insets i = getInsets();
      int contentY = 0;
      int w = b.width - i.right - i.left;
      int h = b.height - i.top - i.bottom;

      if (layeredPane != null) {
        layeredPane.setBounds(i.left, i.top, w, h);
      }
      if (glassPane != null) {
        glassPane.setBounds(i.left, i.top, w, h);
      }
      // Note: This is laying out the children in the layeredPane,
      // technically, these are not our children.
      if (menuBar != null && menuBar.isVisible()) {
        Dimension mbd = menuBar.getPreferredSize();
        menuBar.setBounds(0, 0, w, mbd.height);
        contentY += mbd.height;
      }
      if (contentPane != null) {
        contentPane.setBounds(0, contentY, w, h - contentY);
      }
    }

    public void addLayoutComponent(String name, Component comp) {
    }

    public void removeLayoutComponent(Component comp) {
    }

    public void addLayoutComponent(Component comp, Object constraints) {
    }

    public float getLayoutAlignmentX(Container target) {
      return 0.0f;
    }

    public float getLayoutAlignmentY(Container target) {
      return 0.0f;
    }

    public void invalidateLayout(Container target) {
    }
  }

  /**
   * Returns a string representation of this <code>JRootPane</code>.
   * This method is intended to be used only for debugging purposes,
   * and the content and format of the returned string may vary between
   * implementations. The returned string may be empty but may not
   * be <code>null</code>.
   *
   * @return a string representation of this <code>JRootPane</code>.
   */
  protected String paramString() {
    return super.paramString();
  }

/////////////////
// Accessibility support
////////////////

  /**
   * Gets the <code>AccessibleContext</code> associated with this
   * <code>JRootPane</code>. For root panes, the
   * <code>AccessibleContext</code> takes the form of an
   * <code>AccessibleJRootPane</code>.
   * A new <code>AccessibleJRootPane</code> instance is created if necessary.
   *
   * @return an <code>AccessibleJRootPane</code> that serves as the <code>AccessibleContext</code>
   * of this <code>JRootPane</code>
   */
  public AccessibleContext getAccessibleContext() {
    if (accessibleContext == null) {
      accessibleContext = new AccessibleJRootPane();
    }
    return accessibleContext;
  }

  /**
   * This class implements accessibility support for the
   * <code>JRootPane</code> class.  It provides an implementation of the
   * Java Accessibility API appropriate to root pane user-interface elements.
   * <p>
   * <strong>Warning:</strong>
   * Serialized objects of this class will not be compatible with
   * future Swing releases. The current serialization support is
   * appropriate for short term storage or RMI between applications running
   * the same version of Swing.  As of 1.4, support for long term storage
   * of all JavaBeans&trade;
   * has been added to the <code>java.beans</code> package.
   * Please see {@link java.beans.XMLEncoder}.
   */
  @SuppressWarnings("serial")
  protected class AccessibleJRootPane extends AccessibleJComponent {

    /**
     * Get the role of this object.
     *
     * @return an instance of AccessibleRole describing the role of the object
     */
    public AccessibleRole getAccessibleRole() {
      return AccessibleRole.ROOT_PANE;
    }

    /**
     * Returns the number of accessible children of the object.
     *
     * @return the number of accessible children of the object.
     */
    public int getAccessibleChildrenCount() {
      return super.getAccessibleChildrenCount();
    }

    /**
     * Returns the specified Accessible child of the object.  The Accessible
     * children of an Accessible object are zero-based, so the first child
     * of an Accessible child is at index 0, the second child is at index 1,
     * and so on.
     *
     * @param i zero-based index of child
     * @return the Accessible child of the object
     * @see #getAccessibleChildrenCount
     */
    public Accessible getAccessibleChild(int i) {
      return super.getAccessibleChild(i);
    }
  } // inner class AccessibleJRootPane
}
